-
Notifications
You must be signed in to change notification settings - Fork 350
Compressed offload support for IPC4 #10492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds compressed offload support for IPC4 by refactoring the Cadence codec implementation. It splits the existing implementation into IPC3 and IPC4-specific variants while keeping common functionality shared.
Changes:
- Split Cadence codec implementation into IPC3 (
cadence_ipc3.c) and IPC4 (cadence_ipc4.c) specific files - Modified ring buffer creation to account for module-specific buffer size requirements
- Added support for module initialization data in IPC4
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ipc/ipc4/helper.c | Updated ring buffer size calculation to use MAX of default sizes and module-specific buffer requirements |
| src/include/sof/audio/module_adapter/module/cadence.h | Exposed common Cadence codec functions, added IPC4-specific structures, moved API ID enum from .c file |
| src/include/sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h | Added new MP3 encoder API header with configuration parameters and error codes |
| src/include/ipc4/module.h | Added MODULE_DATA initialization data type to support codec-specific init data |
| src/audio/module_adapter/module_adapter_ipc4.c | Added handling for MODULE_DATA initialization data type |
| src/audio/module_adapter/module/cadence_ipc4.c | New IPC4-specific Cadence codec implementation with DP-aware processing |
| src/audio/module_adapter/module/cadence_ipc3.c | Extracted IPC3-specific Cadence codec implementation |
| src/audio/module_adapter/module/cadence.c | Refactored to contain only common codec functionality shared between IPC3/IPC4 |
| src/audio/module_adapter/CMakeLists.txt | Updated build configuration to compile IPC-specific implementations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| struct cadence_codec_data *cd = module_get_private_data(mod); | ||
| struct comp_dev *dev = mod->dev; | ||
| int word_size = 16; |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded word size value 16 is used here but then validated against audio_fmt.depth in the switch statement below. Consider using a constant definition or deriving the value from the configuration to make the relationship clearer.
|
@dbaluta would you be able to give this PR a try to make sure IPC3 compressed support is still good? On the kernel side, the split was cleaner but I had to retain the common parts in this PR for IPC3 and IPC4. Thanks! |
|
@ranj063 I get the following compile time errors: Looks like you need to add the following fix: Otherwise it works fine. |
| { | ||
| /* set the module init_data */ | ||
| dst->init_data = (const void *)(obj + 1); | ||
| dst->avail = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you verify that dst->avail is set to false before the function call (e.g. through memset)? I.e are we prepared for a situation where item "IPC4_MOD_INIT_DATA_ID_MODULE_DATA" is not present for some reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wjablon1 module_ext_init_decode() is called right after we receive the module init IPC for a module. And when we receive the IPC, "mod" data for the module is allocated right then and it is cleared to 0 with a memset. Is that what you're asking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep. If mod->priv.cfg is memseted to zeros prior to module_adapter_init_data, I don't see an issue here. Otherwise I would manually set dst->avail to false before module_ext_init_decode.
d137da9 to
721418e
Compare
| case IPC4_MOD_INIT_DATA_ID_MODULE_DATA: | ||
| { | ||
| /* set the module init_data */ | ||
| dst->init_data = (const void *)(obj + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't the obj pointer in the IPC buffer, which will be overwritten with the next IPC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also caught my attention but then I noticed that the init_data pointer is set back to NULL after initialization in module_adapter_reset_data. Probably we should also set dst->avail to false in the module_adapter_reset_data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lyakh the idea for this is to just pass the init data pointer to the module-specific init and it is up to the module to take it or not. For example, in the case of the cadence decoder, we save this data which contains the codec params requested by the kernel like here
| ret = memcpy_s(setup_cfg->data, setup_cfg->size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably call this out in the comments that clients must copy if they need to retain the data after IPC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...or maybe we can move that = NULL into this or the calling function and remove module_adapter_reset_data() completely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My votes to set the init_data pointer to NULL after module init is complete and we return from IPC handling. If this cannot be done cleanly, then I think we should do a copy of the data. Otherwise this is like a trap waiting to spring for module developers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another possibility would be passing it as a separate argument to whatever functions need it without assigning it to persistent objects
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kv2019i As I mentioned the pointer is already set to NULL after module initialization in module_adapter_reset_data. I kind of agree with @lyakh. Some form of separation is needed. Either a separate function for unpacking temporary data or a separate destination data structure or maybe some sub-structure of module_config (like dst->tmp_data.init_data).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to take this as-is today but with added doxygen and inline comment stating the need to copy as there is a lot on in progress work around userspace copying of IPC data and this would also benefit by reusing the same. i.e. there is little value in implementing a solution here today when we will need to change it in a few weeks for userspace.
lgirdwood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just some minor opens from me.
| case IPC4_MOD_INIT_DATA_ID_MODULE_DATA: | ||
| { | ||
| /* set the module init_data */ | ||
| dst->init_data = (const void *)(obj + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably call this out in the comments that clients must copy if they need to retain the data after IPC
kv2019i
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing major, but a few questions inline.
| case IPC4_MOD_INIT_DATA_ID_MODULE_DATA: | ||
| { | ||
| /* set the module init_data */ | ||
| dst->init_data = (const void *)(obj + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My votes to set the init_data pointer to NULL after module init is complete and we return from IPC handling. If this cannot be done cleanly, then I think we should do a copy of the data. Otherwise this is like a trap waiting to spring for module developers.
| ring_buffer = ring_buffer_create(dp, MAX(source_get_min_available(src), | ||
| dst_module_data->mpd.in_buff_size), | ||
| MAX(sink_get_min_free_space(snk), | ||
| src_module_data->mpd.out_buff_size), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why this is needed, perhaps with some example? I thought module should advertise its requirements via the sink/source API, so tha tsource_get_min_available() and sink_get_min_free_space() would require bigger values. Directly accessing mpd.in/out_buff_size seems a bit like punching holes through the sink/source (see logic above on L623 and above). I could be missing something, but would be good to record the logic a bit more in the git commit to help the next person that needs to modify this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kv2019i an example is the cadence decoder in the following path that needs this. We do not know what the min size of the input buffer needs to be for this module. We typically use the ibs/obs to calculate this but for the decoder module, the ibs/obs is sort of iirelevant and we typically get the minimum required samples using the cadence API. So this is what it does here.
Add a global ID for module specific init data in the extended init data section and update the decode function to save the data in the module's init_data. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
When a module advertises the input and output buffer requirements for processing, use that to determine the size of the secondary buffer when attaching them to buffers interfacing with DP modules. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
721418e to
9a7f62d
Compare
|
@lyakh @lgirdwood @kv2019i I have updated the PR to add comments for clarification now. Please take alook |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Split the implementation for IPC3 for the cadence decoder and add a new implementation for IPC4. The IPC4 implementation assumes that the codec info is passed to the firmware during the module init IPC as module specific data. The implementation includes support for MP3 decoder, MP3 encoder and AAC decoder for the time being. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
9a7f62d to
dd9f7f2
Compare
This PR is part 1 of the compressed offload support which includes splitting up the cadence implementation for IPC3 and IPC4 along with the required patches for setting a DP module's ring buffer size based on what the input buffer size requirements for the codec are and the init data required for module init. The topology patches showing the compressed path will be included in the next part